#![allow(unused_extern_crates)]
extern crate serde_ignored;
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
extern crate uuid;

use std::sync::Arc;
use std::marker::PhantomData;
use futures::{Future, future, Stream, stream};
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use hyper::header::{Headers, ContentType};
use self::url::form_urlencoded;
use mimetypes;
use serde_json;
use serde_xml_rs;

#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use std::io;

#[allow(unused_imports)]
use std::collections::BTreeSet;

pub use swagger::auth::Authorization;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use swagger::headers::SafeHeaders;

use {Api,
     MultigetGetResponse,
     MultipleAuthSchemeGetResponse,
     ReadonlyAuthSchemeGetResponse,
     RequiredOctetStreamPutResponse,
     ResponsesWithHeadersGetResponse,
     UuidGetResponse,
     XmlExtraPostResponse,
     XmlOtherPostResponse,
     XmlOtherPutResponse,
     XmlPostResponse,
     XmlPutResponse
     };
#[allow(unused_imports)]
use models;

pub mod context;

header! { (Warning, "Warning") => [String] }

mod paths {
    extern crate regex;

    lazy_static! {
        pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
            r"^/multiget$",
            r"^/multiple_auth_scheme$",
            r"^/readonly_auth_scheme$",
            r"^/required_octet_stream$",
            r"^/responses_with_headers$",
            r"^/uuid$",
            r"^/xml$",
            r"^/xml_extra$",
            r"^/xml_other$"
        ]).unwrap();
    }
    pub static ID_MULTIGET: usize = 0;
    pub static ID_MULTIPLE_AUTH_SCHEME: usize = 1;
    pub static ID_READONLY_AUTH_SCHEME: usize = 2;
    pub static ID_REQUIRED_OCTET_STREAM: usize = 3;
    pub static ID_RESPONSES_WITH_HEADERS: usize = 4;
    pub static ID_UUID: usize = 5;
    pub static ID_XML: usize = 6;
    pub static ID_XML_EXTRA: usize = 7;
    pub static ID_XML_OTHER: usize = 8;
}

pub struct NewService<T, C> {
    api_impl: Arc<T>,
    marker: PhantomData<C>,
}

impl<T, C> NewService<T, C>
where
    T: Api<C> + Clone + 'static,
    C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
{
    pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
        NewService{api_impl: api_impl.into(), marker: PhantomData}
    }
}

impl<T, C> hyper::server::NewService for NewService<T, C>
where
    T: Api<C> + Clone + 'static,
    C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
{
    type Request = (Request, C);
    type Response = Response;
    type Error = Error;
    type Instance = Service<T, C>;

    fn new_service(&self) -> Result<Self::Instance, io::Error> {
        Ok(Service::new(self.api_impl.clone()))
    }
}

pub struct Service<T, C> {
    api_impl: Arc<T>,
    marker: PhantomData<C>,
}

impl<T, C> Service<T, C>
where
    T: Api<C> + Clone + 'static,
    C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static {
    pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
        Service{api_impl: api_impl.into(), marker: PhantomData}
    }
}

impl<T, C> hyper::server::Service for Service<T, C>
where
    T: Api<C> + Clone + 'static,
    C: Has<XSpanIdString> + Has<Option<Authorization>> + 'static
{
    type Request = (Request, C);
    type Response = Response;
    type Error = Error;
    type Future = Box<dyn Future<Item=Response, Error=Error>>;

    fn call(&self, (req, mut context): Self::Request) -> Self::Future {
        let api_impl = self.api_impl.clone();
        let (method, uri, _, headers, body) = req.deconstruct();
        let path = paths::GLOBAL_REGEX_SET.matches(uri.path());

        // This match statement is duplicated below in `parse_operation_id()`.
        // Please update both places if changing how this code is autogenerated.
        match &method {

            // MultigetGet - GET /multiget
            &hyper::Method::Get if path.matched(paths::ID_MULTIGET) => {
                Box::new({
                        {{
                                Box::new(api_impl.multiget_get(&context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                MultigetGetResponse::JSONRsp

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_JSON_RSP.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::XMLRsp

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_XML_RSP.clone()));

                                                    let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::OctetRsp

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(202).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_OCTET_RSP.clone()));

                                                    let body = body.0;
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::StringRsp

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(203).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_STRING_RSP.clone()));

                                                    let body = body;
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::DuplicateResponseLongText

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(204).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::DuplicateResponseLongText_2

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(205).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_2.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                                MultigetGetResponse::DuplicateResponseLongText_3

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(206).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_3.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                        }}
                }) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // MultipleAuthSchemeGet - GET /multiple_auth_scheme
            &hyper::Method::Get if path.matched(paths::ID_MULTIPLE_AUTH_SCHEME) => {
                {
                    let authorization = match (&context as &dyn Has<Option<Authorization>>).get() {
                        &Some(ref authorization) => authorization,
                        &None => return Box::new(future::ok(Response::new()
                                                .with_status(StatusCode::Forbidden)
                                                .with_body("Unauthenticated"))),
                    };

                    // Authorization
                    if let Scopes::Some(ref scopes) = authorization.scopes {
                        let required_scopes: BTreeSet<String> = vec![
                            "test.read".to_string(), // Allowed to read state.
                            "test.write".to_string(), // Allowed to change state.
                        ].into_iter().collect();

                        if !required_scopes.is_subset(scopes) {
                            let missing_scopes = required_scopes.difference(scopes);
                            return Box::new(future::ok(Response::new()
                                .with_status(StatusCode::Forbidden)
                                .with_body(missing_scopes.fold(
                                    "Insufficient authorization, missing scopes".to_string(),
                                    |s, scope| format!("{} {}", s, scope)
                                ))
                            ));
                        }
                    }
                }
                Box::new({
                        {{
                                Box::new(api_impl.multiple_auth_scheme_get(&context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                MultipleAuthSchemeGetResponse::CheckThatLimitingToMultipleRequiredAuthSchemesWorks


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                        }}
                }) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
            &hyper::Method::Get if path.matched(paths::ID_READONLY_AUTH_SCHEME) => {
                {
                    let authorization = match (&context as &dyn Has<Option<Authorization>>).get() {
                        &Some(ref authorization) => authorization,
                        &None => return Box::new(future::ok(Response::new()
                                                .with_status(StatusCode::Forbidden)
                                                .with_body("Unauthenticated"))),
                    };

                    // Authorization
                    if let Scopes::Some(ref scopes) = authorization.scopes {
                        let required_scopes: BTreeSet<String> = vec![
                            "test.read".to_string(), // Allowed to read state.
                        ].into_iter().collect();

                        if !required_scopes.is_subset(scopes) {
                            let missing_scopes = required_scopes.difference(scopes);
                            return Box::new(future::ok(Response::new()
                                .with_status(StatusCode::Forbidden)
                                .with_body(missing_scopes.fold(
                                    "Insufficient authorization, missing scopes".to_string(),
                                    |s, scope| format!("{} {}", s, scope)
                                ))
                            ));
                        }
                    }
                }
                Box::new({
                        {{
                                Box::new(api_impl.readonly_auth_scheme_get(&context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                ReadonlyAuthSchemeGetResponse::CheckThatLimitingToASingleRequiredAuthSchemeWorks


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                        }}
                }) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // RequiredOctetStreamPut - PUT /required_octet_stream
            &hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let param_body: Option<swagger::ByteArray> = if !body.is_empty() {
                                    Some(swagger::ByteArray(body.to_vec()))
                                } else {
                                    None
                                };
                                let param_body = match param_body {
                                    Some(param_body) => param_body,
                                    None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required body parameter body"))),
                                };
                                Box::new(api_impl.required_octet_stream_put(param_body, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                RequiredOctetStreamPutResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter body: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // ResponsesWithHeadersGet - GET /responses_with_headers
            &hyper::Method::Get if path.matched(paths::ID_RESPONSES_WITH_HEADERS) => {
                Box::new({
                        {{
                                Box::new(api_impl.responses_with_headers_get(&context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                ResponsesWithHeadersGetResponse::Success

                                                    {
                                                        body,
                                                        success_info
                                                    }


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());
                                                    header! { (ResponseSuccessInfo, "Success-Info") => [String] }
                                                    response.headers_mut().set(ResponseSuccessInfo(success_info));

                                                    response.headers_mut().set(ContentType(mimetypes::responses::RESPONSES_WITH_HEADERS_GET_SUCCESS.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                                ResponsesWithHeadersGetResponse::PreconditionFailed


                                                    {
                                                        further_info, 
                                                        failure_info
                                                    }

                                                => {
                                                    response.set_status(StatusCode::try_from(412).unwrap());
                                                    header! { (ResponseFurtherInfo, "Further-Info") => [String] }
                                                    response.headers_mut().set(ResponseFurtherInfo(further_info));
                                                    header! { (ResponseFailureInfo, "Failure-Info") => [String] }
                                                    response.headers_mut().set(ResponseFailureInfo(failure_info));

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                        }}
                }) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // UuidGet - GET /uuid
            &hyper::Method::Get if path.matched(paths::ID_UUID) => {
                Box::new({
                        {{
                                Box::new(api_impl.uuid_get(&context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        match result {
                                            Ok(rsp) => match rsp {
                                                UuidGetResponse::DuplicateResponseLongText

                                                    (body)


                                                => {
                                                    response.set_status(StatusCode::try_from(200).unwrap());

                                                    response.headers_mut().set(ContentType(mimetypes::responses::UUID_GET_DUPLICATE_RESPONSE_LONG_TEXT.clone()));

                                                    let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
                                                    response.set_body(body);
                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                        }}
                }) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // XmlExtraPost - POST /xml_extra
            &hyper::Method::Post if path.matched(paths::ID_XML_EXTRA) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let mut unused_elements = Vec::new();
                                let param_duplicate_xml_object: Option<models::DuplicateXmlObject> = if !body.is_empty() {
                                    let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
                                    match serde_ignored::deserialize(deserializer, |path| {
                                            warn!("Ignoring unknown field in body: {}", path);
                                            unused_elements.push(path.to_string());
                                    }) {
                                        Ok(param_duplicate_xml_object) => param_duplicate_xml_object,
                                        Err(_) => None,
                                    }
                                } else {
                                    None
                                };
                                Box::new(api_impl.xml_extra_post(param_duplicate_xml_object, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        if !unused_elements.is_empty() {
                                            response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
                                        }

                                        match result {
                                            Ok(rsp) => match rsp {
                                                XmlExtraPostResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                },
                                                XmlExtraPostResponse::BadRequest


                                                => {
                                                    response.set_status(StatusCode::try_from(400).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter DuplicateXmlObject: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // XmlOtherPost - POST /xml_other
            &hyper::Method::Post if path.matched(paths::ID_XML_OTHER) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let mut unused_elements = Vec::new();
                                let param_another_xml_object: Option<models::AnotherXmlObject> = if !body.is_empty() {
                                    let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
                                    match serde_ignored::deserialize(deserializer, |path| {
                                            warn!("Ignoring unknown field in body: {}", path);
                                            unused_elements.push(path.to_string());
                                    }) {
                                        Ok(param_another_xml_object) => param_another_xml_object,
                                        Err(_) => None,
                                    }
                                } else {
                                    None
                                };
                                Box::new(api_impl.xml_other_post(param_another_xml_object, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        if !unused_elements.is_empty() {
                                            response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
                                        }

                                        match result {
                                            Ok(rsp) => match rsp {
                                                XmlOtherPostResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                },
                                                XmlOtherPostResponse::BadRequest


                                                => {
                                                    response.set_status(StatusCode::try_from(400).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter AnotherXmlObject: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // XmlOtherPut - PUT /xml_other
            &hyper::Method::Put if path.matched(paths::ID_XML_OTHER) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let mut unused_elements = Vec::new();
                                let param_string: Option<models::AnotherXmlArray> = if !body.is_empty() {
                                    let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
                                    match serde_ignored::deserialize(deserializer, |path| {
                                            warn!("Ignoring unknown field in body: {}", path);
                                            unused_elements.push(path.to_string());
                                    }) {
                                        Ok(param_string) => param_string,
                                        Err(_) => None,
                                    }
                                } else {
                                    None
                                };
                                Box::new(api_impl.xml_other_put(param_string, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        if !unused_elements.is_empty() {
                                            response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
                                        }

                                        match result {
                                            Ok(rsp) => match rsp {
                                                XmlOtherPutResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                },
                                                XmlOtherPutResponse::BadRequest


                                                => {
                                                    response.set_status(StatusCode::try_from(400).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter string: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // XmlPost - POST /xml
            &hyper::Method::Post if path.matched(paths::ID_XML) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let mut unused_elements = Vec::new();
                                let param_string: Option<models::XmlArray> = if !body.is_empty() {
                                    let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
                                    match serde_ignored::deserialize(deserializer, |path| {
                                            warn!("Ignoring unknown field in body: {}", path);
                                            unused_elements.push(path.to_string());
                                    }) {
                                        Ok(param_string) => param_string,
                                        Err(_) => None,
                                    }
                                } else {
                                    None
                                };
                                Box::new(api_impl.xml_post(param_string, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        if !unused_elements.is_empty() {
                                            response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
                                        }

                                        match result {
                                            Ok(rsp) => match rsp {
                                                XmlPostResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                },
                                                XmlPostResponse::BadRequest


                                                => {
                                                    response.set_status(StatusCode::try_from(400).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter string: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            // XmlPut - PUT /xml
            &hyper::Method::Put if path.matched(paths::ID_XML) => {
                // Body parameters (note that non-required body parameters will ignore garbage
                // values, rather than causing a 400 response). Produce warning header and logs for
                // any unused fields.
                Box::new(body.concat2()
                    .then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
                        match result {
                            Ok(body) => {
                                let mut unused_elements = Vec::new();
                                let param_xml_object: Option<models::XmlObject> = if !body.is_empty() {
                                    let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
                                    match serde_ignored::deserialize(deserializer, |path| {
                                            warn!("Ignoring unknown field in body: {}", path);
                                            unused_elements.push(path.to_string());
                                    }) {
                                        Ok(param_xml_object) => param_xml_object,
                                        Err(_) => None,
                                    }
                                } else {
                                    None
                                };
                                Box::new(api_impl.xml_put(param_xml_object, &context)
                                    .then(move |result| {
                                        let mut response = Response::new();
                                        response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));

                                        if !unused_elements.is_empty() {
                                            response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
                                        }

                                        match result {
                                            Ok(rsp) => match rsp {
                                                XmlPutResponse::OK


                                                => {
                                                    response.set_status(StatusCode::try_from(201).unwrap());

                                                },
                                                XmlPutResponse::BadRequest


                                                => {
                                                    response.set_status(StatusCode::try_from(400).unwrap());

                                                },
                                            },
                                            Err(_) => {
                                                // Application code returned an error. This should not happen, as the implementation should
                                                // return a valid response.
                                                response.set_status(StatusCode::InternalServerError);
                                                response.set_body("An internal error occurred");
                                            },
                                        }

                                        future::ok(response)
                                    }
                                ))
                            },
                            Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter XmlObject: {}", e)))),
                        }
                    })
                ) as Box<dyn Future<Item=Response, Error=Error>>
            },

            _ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box<dyn Future<Item=Response, Error=Error>>,
        }
    }
}

impl<T, C> Clone for Service<T, C>
{
    fn clone(&self) -> Self {
        Service {
            api_impl: self.api_impl.clone(),
            marker: self.marker.clone(),
        }
    }
}


/// Request parser for `Api`.
pub struct ApiRequestParser;
impl RequestParser for ApiRequestParser {
    fn parse_operation_id(request: &Request) -> Result<&'static str, ()> {
        let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
        match request.method() {

            // MultigetGet - GET /multiget
            &hyper::Method::Get if path.matched(paths::ID_MULTIGET) => Ok("MultigetGet"),

            // MultipleAuthSchemeGet - GET /multiple_auth_scheme
            &hyper::Method::Get if path.matched(paths::ID_MULTIPLE_AUTH_SCHEME) => Ok("MultipleAuthSchemeGet"),

            // ReadonlyAuthSchemeGet - GET /readonly_auth_scheme
            &hyper::Method::Get if path.matched(paths::ID_READONLY_AUTH_SCHEME) => Ok("ReadonlyAuthSchemeGet"),

            // RequiredOctetStreamPut - PUT /required_octet_stream
            &hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => Ok("RequiredOctetStreamPut"),

            // ResponsesWithHeadersGet - GET /responses_with_headers
            &hyper::Method::Get if path.matched(paths::ID_RESPONSES_WITH_HEADERS) => Ok("ResponsesWithHeadersGet"),

            // UuidGet - GET /uuid
            &hyper::Method::Get if path.matched(paths::ID_UUID) => Ok("UuidGet"),

            // XmlExtraPost - POST /xml_extra
            &hyper::Method::Post if path.matched(paths::ID_XML_EXTRA) => Ok("XmlExtraPost"),

            // XmlOtherPost - POST /xml_other
            &hyper::Method::Post if path.matched(paths::ID_XML_OTHER) => Ok("XmlOtherPost"),

            // XmlOtherPut - PUT /xml_other
            &hyper::Method::Put if path.matched(paths::ID_XML_OTHER) => Ok("XmlOtherPut"),

            // XmlPost - POST /xml
            &hyper::Method::Post if path.matched(paths::ID_XML) => Ok("XmlPost"),

            // XmlPut - PUT /xml
            &hyper::Method::Put if path.matched(paths::ID_XML) => Ok("XmlPut"),
            _ => Err(()),
        }
    }
}
